package think.in.java.concurrency.practise.exec5;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*;

/**
 * User: yuxinlei
 * Date: 5/19/11
 * Time: 3:40 PM
 */
public class InnerClassWithFuture {

    public static void main(String[] args) {
        //note we can't use this method to invoke the method like this , as theose method as sync , so the async
        //method will not take effort.


        Thread t = new Thread(
                new Runnable() {
                    ExecutorService executorService = Executors.newCachedThreadPool();
                    List<Future<String>> results = new ArrayList<Future<String>>();
                    CountDownLatch countDownLatch = new CountDownLatch(4);

                    public void run() {
                        results.add(executorService.submit(
                                new Callable<String>() {
                                    InnerThread1 innerThread1 = new InnerThread1();

                                    public String call() throws Exception {
                                        return innerThread1.getCurrencyResult();  //To change body of implemented methods use File | Settings | File Templates.
                                    }
                                }
                        ));
                        results.add(executorService.submit(
                                new Callable<String>() {
                                    InnerThread2 innerThread2 = new InnerThread2();

                                    public String call() throws Exception {
                                        return innerThread2.getConcurencyResult();  //To change body of implemented methods use File | Settings | File Templates.
                                    }
                                }
                        ));

                        HashSet<Integer> resultLeftCount = new HashSet<Integer>();
                        while(resultLeftCount.size()<results.size()){
                            for(int i =0 ; i < results.size() ; i++){
                                 resultLeftCount.add(i) ;
                            }
                        }
                        for(int i =0 ; i < results.size() ; i++){
                                 System.out.println("ended "+results.get(i));
                        }
                    }

                }
        );

        t.start();

        System.out.println("main all logic are finished ! ");
    }
}

class InnerThread1 {
    private int count = 50;
    private InnerClass innerClass;

    public InnerThread1() {
        innerClass = new InnerClass();
    }

    public String getCurrencyResult() {
        try {
            ExecutorService executorService = Executors.newCachedThreadPool();

            Future<String> result = executorService.submit(innerClass);
            while (!result.isDone()) {
                Thread.sleep(5);
                Thread.yield();
            }
            String rest = result.get();
            return rest;

        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (ExecutionException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return null;
    }

    private class InnerClass implements Callable<String> {
        public InnerClass() {
            super();
        }


        public String call() throws Exception {
            try {
                while (count > 0) {
                    System.out.println(InnerThread1.class.toString() + "countDown to " + count);
                    count--;
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
            return null;  //To change body of implemented methods use File | Settings | File Templates.
        }
    }
}


class InnerThread2 {
    private int count = 50;

    public InnerThread2() {

    }

    public String getConcurencyResult() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> result = executorService.submit(
                new Callable<String>() {

                    public String call() throws Exception {
                        try {
                            while (count > 0) {
                                System.out.println(InnerThread2.class.toString() + "countDown to " + count);
                                count--;
                                Thread.sleep(100);
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                        }
                        return null;
                    }
                }
        );
        return callableWaiting(result);

    }

    private String callableWaiting(Future<String> result) {
        try {
            while (!result.isDone()) {

                Thread.sleep(5);

                Thread.yield();
            }
            String rest = result.get();
            return rest;

        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (ExecutionException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return null;
    }
}
